/**
  ******************************************************************************
  * @file    main.c
  * @author  AE Team
  * @version 1.0.3
  * @date    2024-05-28
  * @brief   本样例演示 GTIM1 的输入捕捉功能。
  *          通过该功能以测量输入到GTIM1.CH4的脉冲的周期。
  *          GTIM1.CH4输入捕获信号来源通过TI4SEL选择为LSI_OUT即可实现内
  *          部连接，无需外部接线。
  *
  *          通过串口打印GTIM1捕获并通过计算得出的LSI时钟频率
  *          串口参数为115200-8-n-1, TXD=PB02
  *
  * @note    硬件平台：SYM32L010_StartKit_V1.0
  *          接线说明：printf打印需要连接USB线缆，请短接J13、断开J12
  *                    断开J22，通过MCO输出LSI的频率，用示波器查看是否与捕获到的频率一致。
  *
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2024 SIYIMicro.
  * All rights reserved.</center></h2>
  *
  *
  ******************************************************************************
  */


/******************************************************************************/
/* Include files                                                              */
/******************************************************************************/
#include "main.h"
#include "sym32l010_hal_sysctrl.h"
#include "sym32l010_hal_systick.h"
#include "sym32l010_hal_gpio.h"
#include "sym32l010_hal_gtim.h"
#include "sym32l010_startkit_board.h"


/******************************************************************************/
/* Local pre-processor symbols/macros ('#define')                             */
/******************************************************************************/

/******************************************************************************/
/* Global variable definitions (declared in header file with 'extern')        */
/******************************************************************************/
GTIM_HandleTypeDef hgtim1;
uint64_t CaptureCnt = 0;
uint64_t SumPeriod  = 0;

/******************************************************************************/
/* Local type definitions ('typedef')                                         */
/******************************************************************************/

/******************************************************************************/
/* Local function prototypes ('static')                                       */
/******************************************************************************/
static void GTIM1_Init(void);

/******************************************************************************/
/* Local variable definitions ('static')                                      */
/******************************************************************************/

/******************************************************************************/
/* Local pre-processor symbols/macros ('#define')                             */
/******************************************************************************/

/******************************************************************************/
/* Function implementation - global ('extern') and local ('static')           */
/******************************************************************************/


/*******************************************************************************
 ** \brief  Main function of project
 **
 ** \return uint32_t return value, if needed
 **
 **
 ******************************************************************************/
int32_t main(void)
{
    // 系统时钟初始化
    HAL_SysCtrl_ConfigWaitCycle(48000000);
    HAL_SysCtrl_HSI_SetDiv(HSIOSC_TO_HSI48MHZ);

    // 板载 UART 初始化
    Bsp_Uart_Init(48000000, 115200);
    printf("HelloWorld!\r\n");

    // GTIM1 初始化
    GTIM1_Init();

    // 使能LSI并从MCO输出
    HAL_SysCtrl_LSI_Enable();
    HAL_SysCtrl_ClkOut_MCO_PB03(SYSCTRL_MCO_SRC_LSI, SYSCTRL_MCO_DIV1);

    // 发生捕捉后，在中断服务程序中计算捕获的频率
    while (1)
    {
        if ((CaptureCnt % 1000) == 0)
        {
            float Freq = 48000000.0 / (SumPeriod * 1.0 / CaptureCnt);

            printf("Counter = %lld    LSI_Freq = %2.3f\n", CaptureCnt, Freq);

        }
    }
}


/*******************************************************************************
 * @brief  GTIM1 初始化
 * @retval None
 */
static void GTIM1_Init(void)
{
    GTIM_ClockConfigTypeDef GTIM_ClkCgfStruct;
    MemClr(&GTIM_ClkCgfStruct,   sizeof(GTIM_ClkCgfStruct));

    HAL_SYSCTRL_GTIM1_CLK_ENABLE();

    // 初始化GTIM1时基
    MemClr(&hgtim1, sizeof(hgtim1));
    hgtim1.Instance           = SYM_GTIM1;
    hgtim1.Init.Period        = 65536 - 1;
    hgtim1.Init.Prescaler     = 1 - 1;
    hgtim1.Init.CounterMode   = GTIM_COUNTERMODE_UP;
    HAL_GTIM_IC_Init(&hgtim1);

    // 初始化GTIM1输入捕获通道
    hgtim1.IcInit.ICFilter    = 0;
    hgtim1.IcInit.ICPolarity  = GTIM_ICPOLARITY_RISING;
    hgtim1.IcInit.ICPrescaler = GTIM_ICPSC_DIV1;
    hgtim1.IcInit.ICSelection = GTIM_ICSELECTION_DIRECTTI;
    HAL_GTIM_IC_ConfigChannel(&hgtim1, &hgtim1.IcInit, GTIM_CHANNEL_4);

    // 设置GTIM1输入捕获通道的来源
    HAL_GTIM_TISelection(&hgtim1, GTIM_TIxSEL_LSI_OUT, GTIM_CHANNEL_4);

    // 开启内核中断
    NVIC_ClearPendingIRQ(GTIM1_IRQn);
    NVIC_EnableIRQ(GTIM1_IRQn);

    HAL_GTIM_IC_Start_IT(&hgtim1, GTIM_CHANNEL_4);                    // 启动GTIM1.CH4输入捕获
}


/*******************************************************************************
 * @brief  GTIM1 中断服务程序回调函数
 * @param  None
 * @retval None
 *
 */
void GTIM1_IRQHandlerCallBack(void)
{
    static uint16_t Capture1 = 0;
    static uint16_t Capture2 = 0;
    static uint16_t CaptureFlag = 0;

    if (HAL_GTIM_GET_IT_SOURCE(&hgtim1, GTIM_IT_SOURCE_CC4) &&
        HAL_GTIM_GET_FLAG(&hgtim1, GTIM_IT_FLAG_CC4))
    {
        HAL_GTIM_CLR_FLAG(&hgtim1, GTIM_IT_SOURCE_CC4);

        Capture1 = Capture2;
        Capture2 = hgtim1.Instance->CCR4;                             // 通过寄存器获取捕获值
        //Capture2 = HAL_GTIM_GET_COMPARE(&hgtim1, GTIM1_CHANNEL_4);  // 通过函数获取捕获值

        if (CaptureFlag)
        {
            SumPeriod += (Capture2 > Capture1) ? (Capture2 - Capture1) : (Capture2 + 65536 - Capture1);
            CaptureCnt++;
        }
        CaptureFlag = !CaptureFlag;
    }
}


/*******************************************************************************
 ** EOF (not truncated)
 ******************************************************************************/
#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
    /* USER CODE BEGIN */
    /* User can add his own implementation to report the file name and line number,
       tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
    /* USER CODE END */
}
#endif /* USE_FULL_ASSERT */


/************************ (C) COPYRIGHT SIYIMicro *****END OF FILE*************/
